//using K4os.Compression.LZ4;
//using MailKit.Security;
//using MimeKit;
//using MySql.Data.MySqlClient;
//using System.Configuration;
//using System.Text;

//namespace UwinEducation.MySqlBackup
//{
//    public partial class MainForm : Form
//    {
//        public MainForm()
//        {
//            InitializeComponent();
//        }
//    }
//}


using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Web;
using System.Windows.Forms;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq;

namespace UwinEducation.MySqlBackup
{
    public partial class MainForm : Form
    {
        private IConfiguration _configuration;
        private ILogger<MainForm> _logger;
        private System.Timers.Timer _timer;
        private System.Timers.Timer _scheduledTimer; // 新增定时检查计划任务的定时器
        private bool _isBackupRunning;
        private CancellationTokenSource _cancellationTokenSource;
        private ProgressBar progressBar;
        private List<TimeSpan> _scheduledTimes; // 存储计划备份时间
        private DateTime _lastScheduleCheck; // 上次检查计划的时间
        private bool _useMysqlDump; // 是否使用mysqldump备份

        public MainForm()
        {
            // 首先初始化所有UI组件
            InitializeComponents();

            // 然后设置日志系统
            InitializeLogging();

            // 最后设置定时器和其他非UI组件
            InitializeBackupSystem();

            this.textBoxMysqlDumpPath.Text = _configuration?.GetValue<string>("MySqlSettings:MySqlDumpPath") ?? "mysqldump";
        }

        private void InitializeLogging()
        {
            // 初始化配置
            _configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .Build();

            // 初始化日志
            using var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.AddConfiguration(_configuration.GetSection("Logging"));
                builder.Services.AddSingleton<ILoggerProvider>(
                    new RichTextBoxLoggerProvider(richTextBoxLog)
                );
            });
            _logger = loggerFactory.CreateLogger<MainForm>();
        }

        private void InitializeBackupSystem()
        {
            // 初始化定时器
            double intervalMinutes = _configuration
                .GetSection("BackupSettings:BackupIntervalMinutes")
                .Get<double>();
            _timer = new System.Timers.Timer(intervalMinutes * 60 * 1000); // 转换为毫秒
            _timer.Elapsed += Timer_Elapsed;
            _timer.AutoReset = true;

            // 初始化计划备份
            InitializeScheduledBackup();

            _isBackupRunning = false;
            _cancellationTokenSource = new CancellationTokenSource();
            UpdateBackupStatus();
        }

        private void InitializeScheduledBackup()
        {
            // 读取配置的计划备份时间
            _scheduledTimes = new List<TimeSpan>();
            var scheduledTimesConfig = _configuration
                .GetSection("BackupSettings:ScheduledTimes")
                .Get<string[]>();

            if (scheduledTimesConfig != null)
            {
                foreach (var timeStr in scheduledTimesConfig)
                {
                    if (TimeSpan.TryParse(timeStr, out TimeSpan timeSpan))
                    {
                        _scheduledTimes.Add(timeSpan);
                    }
                    else
                    {
                        _logger.LogWarning($"无效的时间格式: {timeStr}");
                    }
                }
            }

            // 设置计划检查定时器，每分钟检查一次
            _scheduledTimer = new System.Timers.Timer(60 * 1000); // 每分钟检查一次
            _scheduledTimer.Elapsed += ScheduledTimer_Elapsed;
            _scheduledTimer.AutoReset = true;

            // 如果启用了计划备份，则启动定时器
            bool enableScheduledBackup = _configuration.GetValue<bool>(
                "BackupSettings:EnableScheduledBackup",
                false
            );
            if (enableScheduledBackup)
            {
                _scheduledTimer.Start();
                _logger.LogInformation(
                    "计划备份已启用，将在以下时间执行: {times}",
                    string.Join(", ", _scheduledTimes.Select(t => t.ToString(@"hh\:mm")))
                );
            }

            _lastScheduleCheck = DateTime.Now;
        }

        private async void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            // 确保窗体句柄已创建
            if (this.IsHandleCreated)
            {
                await StartBackupProcessAsync();
            }
            else
            {
                // 如果窗体句柄未创建，停止定时器，避免继续触发事件
                _timer.Stop();
                _isBackupRunning = false;
            }
        }

        private async void ScheduledTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                // 确保窗体句柄已创建
                if (!this.IsHandleCreated)
                {
                    return;
                }

                DateTime now = DateTime.Now;
                TimeSpan currentTime = new TimeSpan(now.Hour, now.Minute, 0);

                // 检查是否有计划在当前时间执行
                foreach (var scheduledTime in _scheduledTimes)
                {
                    // 检查当前时间是否匹配计划时间（分钟级别）
                    if (Math.Abs((currentTime - scheduledTime).TotalMinutes) < 1)
                    {
                        // 确保在同一分钟内不会重复执行
                        if ((now - _lastScheduleCheck).TotalMinutes >= 1)
                        {
                            _logger.LogInformation(
                                "触发计划备份，当前时间: {now}, 计划时间: {scheduled}",
                                now.ToString("HH:mm"),
                                scheduledTime.ToString(@"hh\:mm")
                            );

                            // 如果没有正在进行的备份，则开始备份
                            if (!_isBackupRunning)
                            {
                                await StartBackupProcessAsync();
                            }

                            _lastScheduleCheck = now;
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "计划备份检查时发生错误");
            }
        }

        // 界面设计
        private void InitializeComponents()
        {
            this.buttonStart = new Button();
            this.buttonStop = new Button();
            this.richTextBoxLog = new RichTextBox();
            this.labelStatus = new Label();
            this.progressBar = new ProgressBar();
            this.buttonSettings = new Button();
            this.radioButtonNative = new RadioButton();
            this.radioButtonMysqlDump = new RadioButton();
            this.labelBackupMethod = new Label();
            this.textBoxMysqlDumpPath = new TextBox();
            this.buttonBrowse = new Button();
            this.StartPosition = FormStartPosition.CenterScreen;
            this.MaximizeBox = false;
            this.Icon = SystemIcons.Application;
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.BackColor = Color.FromArgb(240, 240, 240);

            // 创建面板用于组织控件
            Panel headerPanel = new Panel();
            headerPanel.Dock = DockStyle.Top;
            headerPanel.Height = 70;
            headerPanel.Padding = new Padding(10);

            // 创建标题标签
            Label titleLabel = new Label();
            titleLabel.Text = "MySQL 数据库备份工具";
            titleLabel.Font = new Font("Microsoft YaHei UI", 14, FontStyle.Bold);
            titleLabel.ForeColor = Color.FromArgb(30, 30, 30);
            titleLabel.Location = new Point(15, 15);
            titleLabel.AutoSize = true;
            headerPanel.Controls.Add(titleLabel);

            // buttonStart
            this.buttonStart.Text = "开始备份";
            this.buttonStart.Location = new System.Drawing.Point(20, 20);
            this.buttonStart.Size = new System.Drawing.Size(120, 35);
            this.buttonStart.BackColor = Color.FromArgb(0, 122, 204);
            this.buttonStart.ForeColor = Color.White;
            this.buttonStart.FlatStyle = FlatStyle.Flat;
            this.buttonStart.Font = new Font("Microsoft YaHei UI", 9, FontStyle.Regular);
            this.buttonStart.Cursor = Cursors.Hand;
            this.buttonStart.Click += new EventHandler(this.ButtonStart_Click);

            // buttonStop
            this.buttonStop.Text = "停止备份";
            //this.buttonStop.Enabled = false; // 初始时禁用停止按钮
            this.buttonStop.Location = new System.Drawing.Point(150, 20);
            this.buttonStop.Size = new System.Drawing.Size(120, 35);
            this.buttonStop.BackColor = Color.FromArgb(209, 17, 65);
            this.buttonStop.ForeColor = Color.White;
            this.buttonStop.FlatStyle = FlatStyle.Flat;
            this.buttonStop.Font = new Font("Microsoft YaHei UI", 9, FontStyle.Regular);
            this.buttonStop.Cursor = Cursors.Hand;
            this.buttonStop.Click += new EventHandler(this.ButtonStop_Click);

            // buttonSettings
            this.buttonSettings = new Button();
            this.buttonSettings.Text = "备份设置";
            this.buttonSettings.Location = new System.Drawing.Point(280, 20);
            this.buttonSettings.Size = new System.Drawing.Size(120, 35);
            this.buttonSettings.BackColor = Color.FromArgb(45, 45, 48);
            this.buttonSettings.ForeColor = Color.White;
            this.buttonSettings.FlatStyle = FlatStyle.Flat;
            this.buttonSettings.Font = new Font("Microsoft YaHei UI", 9, FontStyle.Regular);
            this.buttonSettings.Cursor = Cursors.Hand;
            this.buttonSettings.Click += new EventHandler(this.ButtonSettings_Click);

            // 创建按钮面板
            Panel buttonPanel = new Panel();
            buttonPanel.Dock = DockStyle.Top;
            buttonPanel.Height = 75;
            buttonPanel.Padding = new Padding(15, 20, 15, 15);

            // 将按钮添加到面板
            buttonPanel.Controls.Add(this.buttonStart);
            buttonPanel.Controls.Add(this.buttonStop);
            buttonPanel.Controls.Add(this.buttonSettings);

            // labelStatus
            this.labelStatus.Text = "状态：停止";
            this.labelStatus.Location = new System.Drawing.Point(410, 28);
            this.labelStatus.Size = new System.Drawing.Size(200, 30);
            this.labelStatus.Font = new Font("Microsoft YaHei UI", 9, FontStyle.Regular);
            this.labelStatus.ForeColor = Color.FromArgb(30, 30, 30);
            this.labelStatus.TextAlign = ContentAlignment.MiddleRight;
            buttonPanel.Controls.Add(this.labelStatus);

            // 创建备份方法选择面板
            Panel backupMethodPanel = new Panel();
            backupMethodPanel.Dock = DockStyle.Top;
            backupMethodPanel.Height = 110;
            backupMethodPanel.Padding = new Padding(15, 10, 15, 10);
            backupMethodPanel.BackColor = Color.FromArgb(245, 245, 245);
            backupMethodPanel.BorderStyle = BorderStyle.FixedSingle;

            // 备份方法标签
            this.labelBackupMethod = new Label();
            this.labelBackupMethod.Text = "备份方法:";
            this.labelBackupMethod.Location = new Point(15, 15);
            this.labelBackupMethod.Size = new Size(100, 20);
            this.labelBackupMethod.Font = new Font("Microsoft YaHei UI", 9, FontStyle.Regular);
            backupMethodPanel.Controls.Add(this.labelBackupMethod);

            // 内置方法单选按钮
            this.radioButtonNative = new RadioButton();
            this.radioButtonNative.Text = "使用内置方法";
            this.radioButtonNative.Location = new Point(120, 15);
            this.radioButtonNative.Size = new Size(150, 30);
            this.radioButtonNative.Checked = true;
            this.radioButtonNative.CheckedChanged += new EventHandler(this.RadioButtonNative_CheckedChanged);
            backupMethodPanel.Controls.Add(this.radioButtonNative);

            // mysqldump方法单选按钮
            this.radioButtonMysqlDump = new RadioButton();
            this.radioButtonMysqlDump.Text = "使用mysqldump工具";
            this.radioButtonMysqlDump.Location = new Point(280, 15);
            this.radioButtonMysqlDump.Size = new Size(150, 30);
            this.radioButtonMysqlDump.CheckedChanged += new EventHandler(this.RadioButtonMysqlDump_CheckedChanged);
            backupMethodPanel.Controls.Add(this.radioButtonMysqlDump);

            // mysqldump路径文本框
            this.textBoxMysqlDumpPath = new TextBox();
            this.textBoxMysqlDumpPath.Location = new Point(120, 55);
            this.textBoxMysqlDumpPath.Size = new Size(280, 23);
            this.textBoxMysqlDumpPath.Text = _configuration?.GetValue<string>("MySqlSettings:MySqlDumpPath") ?? "mysqldump";
            this.textBoxMysqlDumpPath.Enabled = false;
            backupMethodPanel.Controls.Add(this.textBoxMysqlDumpPath);

            // 浏览按钮
            this.buttonBrowse = new Button();
            this.buttonBrowse.Text = "浏览...";
            this.buttonBrowse.Location = new Point(410, 55);
            this.buttonBrowse.Size = new Size(80, 30);
            this.buttonBrowse.Enabled = false;
            this.buttonBrowse.Click += new EventHandler(this.ButtonBrowse_Click);
            backupMethodPanel.Controls.Add(this.buttonBrowse);

            // 创建进度条面板
            Panel progressPanel = new Panel();
            progressPanel.Dock = DockStyle.Top;
            progressPanel.Height = 50;
            progressPanel.Padding = new Padding(15, 10, 15, 15);

            // progressBar
            this.progressBar.Dock = DockStyle.Fill;
            this.progressBar.Minimum = 0;
            this.progressBar.Maximum = 100;
            this.progressBar.Value = 0;
            this.progressBar.Height = 25;
            progressPanel.Controls.Add(this.progressBar);

            // 创建日志面板
            Panel logPanel = new Panel();
            logPanel.Dock = DockStyle.Fill;
            logPanel.Padding = new Padding(15);

            // richTextBoxLog
            this.richTextBoxLog.Dock = DockStyle.Fill;
            this.richTextBoxLog.ReadOnly = true;
            this.richTextBoxLog.BackColor = Color.White;
            this.richTextBoxLog.BorderStyle = BorderStyle.FixedSingle;
            this.richTextBoxLog.Font = new Font("Consolas", 9F, FontStyle.Regular);
            logPanel.Controls.Add(this.richTextBoxLog);

            // 添加面板到窗体
            this.Controls.Add(logPanel);
            this.Controls.Add(progressPanel);
            this.Controls.Add(backupMethodPanel);
            this.Controls.Add(buttonPanel);
            this.Controls.Add(headerPanel);

            // 窗体设置
            this.Text = "MySQL 数据库备份工具";
            this.Size = new System.Drawing.Size(1000, 800);
            this.MinimumSize = new System.Drawing.Size(820, 600);
            this.Padding = new Padding(0);
        }

        private Button buttonStart;
        private Button buttonStop;
        private Button buttonSettings;
        private RichTextBox richTextBoxLog;
        private Label labelStatus;
        private RadioButton radioButtonNative;
        private RadioButton radioButtonMysqlDump;
        private Label labelBackupMethod;
        private TextBox textBoxMysqlDumpPath;
        private Button buttonBrowse;

        private void RadioButtonNative_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonNative.Checked)
            {
                _useMysqlDump = false;
                textBoxMysqlDumpPath.Enabled = false;
                buttonBrowse.Enabled = false;
                _logger.LogInformation("已切换到内置备份方法");
            }
        }

        private void RadioButtonMysqlDump_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonMysqlDump.Checked)
            {
                _useMysqlDump = true;
                textBoxMysqlDumpPath.Enabled = true;
                buttonBrowse.Enabled = true;
                _logger.LogInformation("已切换到mysqldump备份方法");
            }
        }

        private void ButtonBrowse_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "mysqldump可执行文件|mysqldump.exe;*.exe|所有文件|*.*";
                openFileDialog.Title = "选择mysqldump可执行文件";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    textBoxMysqlDumpPath.Text = openFileDialog.FileName;

                    // 保存到配置
                    SaveMySqlDumpPath(openFileDialog.FileName);
                }
            }
        }

        private void SaveMySqlDumpPath(string path)
        {
            try
            {
                // 读取当前配置文件
                string configPath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
                string json = File.ReadAllText(configPath);

                // 解析为动态对象
                dynamic config = JObject.Parse(json);

                // 更新设置
                if (config.MySqlSettings == null)
                {
                    config.MySqlSettings = new JObject();
                }

                // 更新mysqldump路径
                config.MySqlSettings["MySqlDumpPath"] = path;

                // 保存回文件
                string updatedJson = config.ToString();
                File.WriteAllText(configPath, updatedJson);

                // 重新加载配置
                _configuration = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .Build();

                _logger.LogInformation($"已保存mysqldump路径: {path}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存mysqldump路径时发生错误");
            }
        }

        private async void ButtonStart_Click(object sender, EventArgs e)
        {
            if (!_isBackupRunning)
            {
                await StartBackupProcessAsync();

                // 根据配置决定是否启用间隔备份
                bool enableIntervalBackup = _configuration.GetValue<bool>(
                    "BackupSettings:EnableIntervalBackup",
                    true
                );
                if (enableIntervalBackup)
                {
                    _timer.Start();
                    _logger.LogInformation(
                        "间隔备份已启用，每 {interval} 分钟执行一次",
                        _configuration.GetValue<double>("BackupSettings:BackupIntervalMinutes", 60)
                    );
                }

                // 启用计划备份
                bool enableScheduledBackup = _configuration.GetValue<bool>(
                    "BackupSettings:EnableScheduledBackup",
                    false
                );
                if (enableScheduledBackup && !_scheduledTimer.Enabled)
                {
                    _scheduledTimer.Start();
                    _logger.LogInformation("计划备份已启用");
                    //buttonStart.Enabled = false;
                    //buttonStop.Enabled = true;
                }
            }
        }

        private async Task StartBackupProcessAsync()
        {
            if (_isBackupRunning)
                return;

            _isBackupRunning = true;
            _cancellationTokenSource = new CancellationTokenSource();
            UpdateBackupStatus();

            // 禁用开始按钮
            if (this.IsHandleCreated)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(
                        (MethodInvoker)
                            delegate
                            {
                                buttonStart.Enabled = false;
                            }
                    );
                }
                else
                {
                    buttonStart.Enabled = false;
                }
            }

            try
            {
                _logger.LogInformation("备份服务已启动");
                await PerformBackupAsync(_cancellationTokenSource.Token);
            }
            catch (OperationCanceledException)
            {
                _logger.LogInformation("备份操作已取消");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "备份过程中发生错误");
            }
            finally
            {
                // 启用开始按钮
                if (this.IsHandleCreated)
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(
                            (MethodInvoker)
                                delegate
                                {
                                    buttonStart.Enabled = true;
                                    progressBar.Value = 0;
                                }
                        );
                    }
                    else
                    {
                        buttonStart.Enabled = true;
                        progressBar.Value = 0;
                    }
                }
            }
        }

        private void ButtonStop_Click(object sender, EventArgs e)
        {
            if (_isBackupRunning)
            {
                _cancellationTokenSource.Cancel();
            }

            _timer.Stop();
            _scheduledTimer.Stop();
            _isBackupRunning = false;
            UpdateBackupStatus();
            _logger.LogInformation("备份服务已停止");
            //buttonStart.Enabled = true;
            //buttonStop.Enabled = false;

        }

        private void UpdateBackupStatus()
        {
            if (this.InvokeRequired && this.IsHandleCreated)
            {
                this.Invoke(
                    (MethodInvoker)
                        delegate
                        {
                            labelStatus.Text = $"状态：{(_isBackupRunning ? "运行中" : "停止")}";
                        }
                );
            }
            else if (this.IsHandleCreated)
            {
                labelStatus.Text = $"状态：{(_isBackupRunning ? "运行中" : "停止")}";
            }
        }

        private void UpdateProgress(int percentage, string message = null)
        {
            if (this.InvokeRequired && this.IsHandleCreated)
            {
                this.Invoke(
                    (MethodInvoker)
                        delegate
                        {
                            UpdateProgressInternal(percentage, message);
                        }
                );
            }
            else if (this.IsHandleCreated)
            {
                UpdateProgressInternal(percentage, message);
            }
        }

        private void UpdateProgressInternal(int percentage, string message)
        {
            progressBar.Value = Math.Min(percentage, 100);
            if (!string.IsNullOrEmpty(message))
            {
                _logger.LogInformation(message);
            }
        }

        private async Task PerformBackupAsync(CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始备份数据库: {Time}", DateTime.Now);
                UpdateProgress(0, "准备备份...");

                string connectionString = _configuration["MySqlSettings:ConnectionString"];
                string backupPath = _configuration["MySqlSettings:BackupPath"];
                string backupFileName;

                Directory.CreateDirectory(backupPath);

                // 根据选择的备份方法执行备份
                if (_useMysqlDump)
                {
                    // 使用mysqldump方法
                    string mysqlDumpPath = textBoxMysqlDumpPath.Text;

                    // 从连接字符串中提取信息
                    MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(connectionString);

                    // 创建MySqlDumpBackup实例
                    var mysqlDumpBackup = new MySqlDumpBackup(
                        _logger,
                        mysqlDumpPath,
                        builder.Server,
                        (int)builder.Port,
                        builder.UserID,
                        builder.Password,
                        builder.Database,
                        backupPath,
                        UpdateProgress
                    );
                    // 执行备份
                    backupFileName = await mysqlDumpBackup.BackupDatabaseAsync(cancellationToken);
                }
                else
                {
                    // 使用内置方法
                    backupFileName = $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.sql";
                    string backupFilePath = Path.Combine(backupPath, backupFileName);

                    await BackupDatabaseAsync(connectionString, backupFilePath, cancellationToken);
                }

                UpdateProgress(100, "数据库备份成功");
                _logger.LogInformation("数据库备份成功: {FileName}", backupFileName);

                // 压缩备份文件
                string zipFileName = $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.zip";
                string zipFilePath = Path.Combine(backupPath, zipFileName);
                
                try
                {
                    // 使用单独的文件路径进行压缩
                    string backupFilePath = Path.Combine(backupPath, backupFileName);
                    using (FileStream fs = new FileStream(zipFilePath, FileMode.Create))
                    using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create))
                    {
                        // 添加备份文件到压缩包
                        archive.CreateEntryFromFile(backupFilePath, backupFileName);
                    }
                    
                    // 压缩完成后，删除原始备份文件
                    if (File.Exists(backupFilePath))
                    {
                        File.Delete(backupFilePath);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "压缩或删除备份文件时发生错误: {Message}", ex.Message);
                }

                // 如果需要发送邮件通知，取消注释以下代码
                await SendEmailAsync(zipFileName);
            }
            catch (OperationCanceledException)
            {
                _logger.LogWarning("备份操作已取消");
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "备份或邮件发送失败");
                throw;
            }
            finally
            {
                _isBackupRunning = false;
                UpdateBackupStatus();
            }
        }

        private async Task BackupDatabaseAsync(
            string connectionString,
            string backupFilePath,
            CancellationToken cancellationToken
        )
        {
            MySqlConnection connection = null;

            try
            {
                UpdateProgress(5, "连接数据库...");
                connection = new MySqlConnection(connectionString);
                await connection.OpenAsync(cancellationToken);

                UpdateProgress(10, "获取数据库表结构...");
                var tables = new List<string>();
                var schemaCmd = connection.CreateCommand();
                schemaCmd.CommandText = "SHOW TABLES";
                using var reader = await schemaCmd.ExecuteReaderAsync(cancellationToken);
                while (await reader.ReadAsync(cancellationToken))
                {
                    tables.Add(reader.GetString(0));
                }
                reader.Close();

                UpdateProgress(15, $"开始备份 {tables.Count} 个表...");

                // 使用缓冲写入以提高性能
                await using var fileStream = new FileStream(
                    backupFilePath,
                    FileMode.Create,
                    FileAccess.Write,
                    FileShare.None,
                    8192,
                    true
                );
                await using var writer = new StreamWriter(fileStream, Encoding.UTF8);

                // 写入文件头
                await writer.WriteLineAsync(
                    $"-- MySQL数据库备份\n-- 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n-- 服务器版本: {connection.ServerVersion}\n\n"
                );
                await writer.WriteLineAsync("SET NAMES utf8mb4;");
                await writer.WriteLineAsync("SET FOREIGN_KEY_CHECKS = 0;\n");

                int currentTable = 0;
                int totalTables = tables.Count;

                // 先写入所有表结构
                UpdateProgress(20, "导出表结构...");
                foreach (string table in tables)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    currentTable++;
                    int progress = 20 + (currentTable * 30) / totalTables; // 表结构占总进度的30%
                    UpdateProgress(progress, $"导出表结构 ({currentTable}/{totalTables}): {table}");

                    await writer.WriteLineAsync($"\n-- 表结构: `{table}`\n");
                    await writer.WriteLineAsync($"DROP TABLE IF EXISTS `{table}`;");

                    var createTableCmd = connection.CreateCommand();
                    createTableCmd.CommandText = $"SHOW CREATE TABLE `{table}`";
                    using var createReader = await createTableCmd.ExecuteReaderAsync(
                        cancellationToken
                    );
                    if (await createReader.ReadAsync(cancellationToken))
                    {
                        await writer.WriteLineAsync(createReader.GetString(1) + ";\n");
                    }
                    createReader.Close();
                }

                // 再写入所有表数据
                currentTable = 0;
                UpdateProgress(50, "导出表数据...");
                foreach (string table in tables)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    currentTable++;
                    int progress = 50 + (currentTable * 45) / totalTables; // 表数据占总进度的45%
                    UpdateProgress(progress, $"导出表数据 ({currentTable}/{totalTables}): {table}");

                    var countCmd = connection.CreateCommand();
                    countCmd.CommandText = $"SELECT COUNT(*) FROM `{table}`";
                    long rowCount = (long)await countCmd.ExecuteScalarAsync(cancellationToken);

                    if (rowCount > 0)
                    {
                        await writer.WriteLineAsync($"\n-- 表数据: `{table}`\n");

                        // 分批处理数据，避免一次性加载过多数据
                        const int batchSize = 1000;
                        long processedRows = 0;

                        while (processedRows < rowCount)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            var dataCmd = connection.CreateCommand();
                            dataCmd.CommandText =
                                $"SELECT * FROM `{table}` LIMIT {processedRows}, {batchSize}";
                            using var dataReader = await dataCmd.ExecuteReaderAsync(
                                cancellationToken
                            );

                            StringBuilder insertBuilder = new StringBuilder();
                            bool hasRows = false;

                            while (await dataReader.ReadAsync(cancellationToken))
                            {
                                if (!hasRows)
                                {
                                    insertBuilder.Append($"INSERT INTO `{table}` VALUES ");
                                    hasRows = true;
                                }
                                else
                                {
                                    insertBuilder.Append(",");
                                }

                                insertBuilder.Append("(");
                                for (int i = 0; i < dataReader.FieldCount; i++)
                                {
                                    if (i > 0)
                                        insertBuilder.Append(", ");

                                    if (await dataReader.IsDBNullAsync(i, cancellationToken))
                                    {
                                        insertBuilder.Append("NULL");
                                    }
                                    else
                                    {
                                        var value = dataReader.GetValue(i);
                                        if (value is string || value is DateTime || value is char)
                                        {
                                            insertBuilder.Append(
                                                $"'{MySqlHelper.EscapeString(value.ToString())}'"
                                            );
                                        }
                                        else if (value is bool boolValue)
                                        {
                                            insertBuilder.Append(boolValue ? "1" : "0");
                                        }
                                        else
                                        {
                                            insertBuilder.Append(value.ToString());
                                        }
                                    }
                                }
                                insertBuilder.Append(")");

                                // 每500行写入一次，避免字符串过长
                                if (insertBuilder.Length > 1000000)
                                {
                                    insertBuilder.Append(";");
                                    await writer.WriteLineAsync(insertBuilder.ToString());
                                    insertBuilder.Clear();
                                    hasRows = false;
                                }
                            }

                            if (hasRows)
                            {
                                insertBuilder.Append(";");
                                await writer.WriteLineAsync(insertBuilder.ToString());
                            }

                            dataReader.Close();
                            processedRows += batchSize;
                        }
                    }
                }

                // 写入文件尾
                await writer.WriteLineAsync("\nSET FOREIGN_KEY_CHECKS = 1;");

                UpdateProgress(95, "完成备份文件写入...");
            }
            catch (MySqlException ex)
            {
                _logger.LogError(ex, "MySQL 连接或查询失败: {Message}", ex.Message);
                throw;
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                    throw;
                _logger.LogError(ex, "备份过程中发生错误: {Message}", ex.Message);
                throw;
            }
            finally
            {
                if (connection != null && connection.State == System.Data.ConnectionState.Open)
                {
                    await connection.CloseAsync();
                }
            }
        }

        private async Task SendEmailAsync(string backupFileName)
        {
            try
            {
                UpdateProgress(98, "发送邮件通知...");

                // 获取完整的备份文件路径
                string backupPath = _configuration["MySqlSettings:BackupPath"];
                string backupFilePath = Path.Combine(backupPath, backupFileName);

                // 检查文件是否存在
                if (!File.Exists(backupFilePath))
                {
                    _logger.LogWarning($"备份文件不存在: {backupFilePath}，邮件将不包含附件");
                }

                var message = new MailMessage();
                message.From = new MailAddress(
                    _configuration["EmailSettings:FromEmail"],
                    "Backup Service"
                );

                // 支持多个收件人
                string toEmailsString = _configuration["EmailSettings:ToEmail"];
                if (!string.IsNullOrEmpty(toEmailsString))
                {
                    // 分割多个邮箱地址（以逗号、分号或空格分隔）
                    string[] toEmails = toEmailsString.Split(
                        new char[] { ',', ';', ' ' },
                        StringSplitOptions.RemoveEmptyEntries
                    );

                    foreach (string email in toEmails)
                    {
                        string trimmedEmail = email.Trim();
                        if (!string.IsNullOrEmpty(trimmedEmail))
                        {
                            try
                            {
                                message.To.Add(new MailAddress(trimmedEmail));
                                _logger.LogInformation($"添加收件人: {trimmedEmail}");
                            }
                            catch (FormatException)
                            {
                                _logger.LogWarning($"邮箱格式不正确，已跳过: {trimmedEmail}");
                            }
                        }
                    }

                    // 如果没有有效的收件人，添加默认收件人
                    if (message.To.Count == 0)
                    {
                        _logger.LogWarning("未找到有效的收件人邮箱，使用发件人地址作为收件人");
                        message.To.Add(new MailAddress(_configuration["EmailSettings:FromEmail"]));
                    }
                }
                else
                {
                    // 如果未配置收件人，使用发件人地址
                    message.To.Add(new MailAddress(_configuration["EmailSettings:FromEmail"]));
                }

                message.Subject = $"数据库备份完成 - {backupFileName}";
                message.Body =
                    $"数据库备份已于 {DateTime.Now} 完成。\n\n备份文件: {backupFileName}\n大小: {GetFileSize(backupFilePath)}\n\n此邮件由自动备份系统发送。";
                message.IsBodyHtml = false;

                // 添加备份文件作为附件
                if (File.Exists(backupFilePath))
                {
                    try
                    {
                        // 检查文件大小，如果超过10MB则不添加附件
                        FileInfo fileInfo = new FileInfo(backupFilePath);
                        if (fileInfo.Length > 10 * 1024 * 1024) // 10MB
                        {
                            _logger.LogWarning(
                                $"备份文件过大 ({GetFileSize(backupFilePath)})，超过10MB限制，不会作为附件发送"
                            );
                            message.Body +=
                                "\n\n注意：备份文件过大，未作为附件发送。请直接从备份目录获取文件。";
                        }
                        else
                        {
                            message.Attachments.Add(new Attachment(backupFilePath));
                            _logger.LogInformation(
                                $"已添加附件: {backupFileName} ({GetFileSize(backupFilePath)})"
                            );
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "添加附件时发生错误");
                        message.Body += "\n\n注意：添加附件时发生错误，邮件不包含备份文件。";
                    }
                }

                using var client = new SmtpClient(
                    _configuration["EmailSettings:SmtpServer"],
                    _configuration.GetSection("EmailSettings:SmtpPort").Get<int>()
                );
                client.EnableSsl = true;
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.UseDefaultCredentials = false;

                // 检查是否是QQ邮箱，自动设置正确的端口
                string smtpServer = _configuration["EmailSettings:SmtpServer"]?.ToLower();
                if (smtpServer?.Contains("qq.com") == true)
                {
                    _logger.LogInformation("检测到QQ邮箱，确保使用正确的端口(587或465)和SSL设置");
                    // QQ邮箱必须启用SSL
                    client.EnableSsl = true;

                    // 如果端口不是587或465，记录警告
                    int port = _configuration.GetSection("EmailSettings:SmtpPort").Get<int>();
                    if (port != 587 && port != 465)
                    {
                        _logger.LogWarning($"QQ邮箱通常使用端口587或465，当前配置使用的是{port}");
                    }
                }

                client.Credentials = new NetworkCredential(
                    _configuration["EmailSettings:SmtpUsername"],
                    _configuration["EmailSettings:SmtpPassword"]
                );

                _logger.LogInformation($"开始发送邮件到 {message.To.Count} 个收件人...");

                try
                {
                    // 设置超时时间
                    client.Timeout = 60000; // 30秒
                    await client.SendMailAsync(message);
                    _logger.LogInformation("邮件发送成功");
                }
                catch (SmtpException smtpEx)
                {
                    _logger.LogError(smtpEx, $"SMTP错误: {smtpEx.StatusCode}, {smtpEx.Message}");

                    // 尝试使用同步方法发送
                    _logger.LogInformation("尝试使用同步方法发送邮件...");
                    client.Send(message);
                    _logger.LogInformation("使用同步方法发送邮件成功");
                }
                finally
                {
                    // 释放附件资源
                    if (message.Attachments.Count > 0)
                    {
                        foreach (var attachment in message.Attachments)
                        {
                            attachment.Dispose();
                        }
                    }
                }

                UpdateProgress(100, "邮件通知发送成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送邮件失败: {Message}", ex.Message);
                UpdateProgress(100, $"邮件发送失败: {ex.Message}");
                // 不抛出异常，让备份过程继续完成
            }
        }

        // 获取文件大小的可读形式
        private string GetFileSize(string filePath)
        {
            if (!File.Exists(filePath))
                return "未知";

            try
            {
                FileInfo fileInfo = new FileInfo(filePath);
                long bytes = fileInfo.Length;

                if (bytes < 1024)
                    return $"{bytes} B";
                else if (bytes < 1024 * 1024)
                    return $"{bytes / 1024.0:0.00} KB";
                else if (bytes < 1024 * 1024 * 1024)
                    return $"{bytes / (1024.0 * 1024.0):0.00} MB";
                else
                    return $"{bytes / (1024.0 * 1024.0 * 1024.0):0.00} GB";
            }
            catch
            {
                return "未知";
            }
        }

        private void ButtonSettings_Click(object sender, EventArgs e)
        {
            // 创建设置对话框
            using (var settingsForm = new BackupSettingsForm(_configuration, _scheduledTimes))
            {
                if (settingsForm.ShowDialog() == DialogResult.OK)
                {
                    // 更新计划备份时间
                    _scheduledTimes = settingsForm.ScheduledTimes;

                    // 保存设置到配置文件
                    SaveSettings();

                    // 重新初始化备份系统
                    _timer.Stop();
                    _scheduledTimer.Stop();

                    InitializeBackupSystem();

                    _logger.LogInformation("备份设置已更新");
                }
            }
        }

        private void SaveSettings()
        {
            try
            {
                // 读取当前配置文件
                string configPath = Path.Combine(
                    Directory.GetCurrentDirectory(),
                    "appsettings.json"
                );
                string json = File.ReadAllText(configPath);

                // 解析为动态对象
                dynamic config = JObject.Parse(json);

                // 更新设置
                if (config.BackupSettings == null)
                {
                    config.BackupSettings = new JObject();
                }

                // 更新计划时间
                var scheduledTimes = new JArray();
                foreach (var time in _scheduledTimes)
                {
                    scheduledTimes.Add(time.ToString(@"hh\:mm"));
                }
                config.BackupSettings["ScheduledTimes"] = scheduledTimes;

                // 保存回文件
                string updatedJson = config.ToString();
                File.WriteAllText(configPath, updatedJson);

                // 重新加载配置
                _configuration = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .Build();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存设置时发生错误");
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            
        }
    }

    // 自定义日志记录器，将日志写入 RichTextBox
    public class RichTextBoxLoggerProvider : ILoggerProvider
    {
        private readonly RichTextBox _richTextBox;

        public RichTextBoxLoggerProvider(RichTextBox richTextBox)
        {
            _richTextBox = richTextBox;
        }

        public ILogger CreateLogger(string categoryName)
        {
            return new RichTextBoxLogger(_richTextBox);
        }

        public void Dispose() { }
    }

    public class RichTextBoxLogger : ILogger
    {
        private readonly RichTextBox _richTextBox;
        private readonly List<string> _pendingLogs = new List<string>();
        private readonly object _lockObj = new object();
        private const int MaxLogLines = 1000; // 最大日志行数
        private const int CleanupThreshold = 1200; // 触发清理的阈值
        private const int LinesToKeep = 800; // 清理后保留的行数

        public RichTextBoxLogger(RichTextBox richTextBox)
        {
            _richTextBox = richTextBox;

            // 为RichTextBox添加句柄创建事件，以便在控件可用时输出之前缓存的日志
            _richTextBox.HandleCreated += (s, e) =>
            {
                lock (_lockObj)
                {
                    foreach (var log in _pendingLogs)
                    {
                        try
                        {
                            AppendLogWithCleanupCheck(log, LogLevel.Information);
                        }
                        catch { }
                    }
                    _pendingLogs.Clear();
                }
            };
        }

        public IDisposable BeginScope<TState>(TState state) => null;

        public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Information;

        public void Log<TState>(
            LogLevel logLevel,
            EventId eventId,
            TState state,
            Exception exception,
            Func<TState, Exception, string> formatter
        )
        {
            if (!IsEnabled(logLevel))
                return;

            string message =
                $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {logLevel}: {formatter(state, exception)}";

            try
            {
                if (_richTextBox == null || _richTextBox.IsDisposed)
                    return;

                if (!_richTextBox.IsHandleCreated)
                {
                    // 如果控件句柄尚未创建，将日志保存到缓存
                    lock (_lockObj)
                    {
                        _pendingLogs.Add(message);

                        // 控制缓存大小
                        if (_pendingLogs.Count > MaxLogLines)
                        {
                            _pendingLogs.RemoveRange(0, _pendingLogs.Count - LinesToKeep);
                        }
                    }
                    return;
                }

                if (_richTextBox.InvokeRequired)
                {
                    try
                    {
                        _richTextBox.Invoke(
                            (MethodInvoker)
                                delegate
                                {
                                    AppendLogWithCleanupCheck(message, logLevel);
                                }
                        );
                    }
                    catch (InvalidOperationException)
                    {
                        // 控件可能在调用过程中被处置
                        lock (_lockObj)
                        {
                            _pendingLogs.Add(message);
                        }
                    }
                }
                else
                {
                    AppendLogWithCleanupCheck(message, logLevel);
                }
            }
            catch
            {
                // 忽略任何异常，确保日志记录不会导致应用程序崩溃
            }
        }

        private void AppendLogWithCleanupCheck(string message, LogLevel logLevel)
        {
            try
            {
                if (_richTextBox == null || _richTextBox.IsDisposed)
                    return;

                // 检查是否需要清理日志
                int lineCount = _richTextBox.Lines.Length;
                if (lineCount > CleanupThreshold)
                {
                    CleanupLogs();
                }

                _richTextBox.SelectionColor = logLevel == LogLevel.Error ? Color.Red : Color.Black;
                _richTextBox.AppendText(message + Environment.NewLine);
                _richTextBox.ScrollToCaret();
            }
            catch
            {
                // 忽略任何异常
            }
        }

        private void CleanupLogs()
        {
            try
            {
                // 禁用重绘以提高性能
                _richTextBox.SuspendLayout();

                // 计算要保留的文本
                string[] allLines = _richTextBox.Lines;
                if (allLines.Length <= LinesToKeep)
                    return;

                int startIndex = allLines.Length - LinesToKeep;
                string[] linesToKeep = new string[LinesToKeep];
                Array.Copy(allLines, startIndex, linesToKeep, 0, LinesToKeep);

                // 清空文本框并添加保留的行
                _richTextBox.Clear();
                _richTextBox.AppendText(string.Join(Environment.NewLine, linesToKeep));
                _richTextBox.AppendText(Environment.NewLine);

                // 添加清理信息
                _richTextBox.SelectionColor = Color.Blue;
                _richTextBox.AppendText(
                    $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 系统: 已清理较早的 {startIndex} 行日志记录{Environment.NewLine}"
                );

                // 恢复重绘
                _richTextBox.ResumeLayout();

                // 滚动到底部
                _richTextBox.SelectionStart = _richTextBox.Text.Length;
                _richTextBox.ScrollToCaret();
            }
            catch
            {
                // 忽略清理过程中的异常
            }
        }
    }
}
